﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;
using MetadataDocumentationGenerator.DelegatesHelpers;
using MetadataDocumentationGenerator.Helpers;
using MetadataDocumentationGenerator.Properties;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Metadata;

namespace MetadataDocumentationGenerator.Controls
{
    /// <summary>
    /// User control for attributes selection
    /// </summary>
    public partial class Step3 : UserControl, IStepControl
    {
        #region Variables

        /// <summary>
        /// Settings for generation
        /// </summary>
        private readonly GenerationSettings _settings;
        
        /// <summary>
        /// IORganization service
        /// </summary>
        private readonly IOrganizationService _service;
        
        /// <summary>
        /// Metadata for current entity attributes selection
        /// </summary>
        private readonly EntityMetadata _emd;

        #endregion Variables

        #region Constructor

        /// <summary>
        /// Initializes a new instance of class Step3
        /// </summary>
        /// <param name="settings">Generation settings</param>
        /// <param name="service">IOrganization service</param>
        /// <param name="emd">Current entity metadata</param>
        public Step3(GenerationSettings settings, IOrganizationService service, EntityMetadata emd)
        {
            InitializeComponent();

            _settings = settings;
            _service = service;
            _emd = emd;

            // Displays current entity display name on header
            label1.Text = string.Format(label1.Text, _emd.DisplayName.UserLocalizedLabel != null ? _emd.DisplayName.UserLocalizedLabel.Label : _emd.SchemaName);
        }

        #endregion Constructor

        #region User control handlers

        private void Step3Load(object sender, EventArgs e)
        {
            var bwFillAttributes = new BackgroundWorker();
            bwFillAttributes.DoWork += BwFillAttributesDoWork;
            bwFillAttributes.RunWorkerCompleted += BwFillAttributesRunWorkerCompleted;
            bwFillAttributes.RunWorkerAsync();
        }

        private void BtnClearClick(object sender, EventArgs e)
        {
            foreach(ListViewItem item in lvAttributes.Items)
            {
                item.Checked = false;
            }
        }

        private void BtnOnFormClick(object sender, EventArgs e)
        {
            foreach (var item in lvAttributes.Items.Cast<ListViewItem>().Where(item => item.SubItems[2].Text == true.ToString(CultureInfo.InvariantCulture)))
            {
                item.Checked = true;
            }
        }

        private void BtnAllClick(object sender, EventArgs e)
        {
            foreach (ListViewItem item in lvAttributes.Items)
            {
                item.Checked = true;
            }
        }

        #endregion User control handlers

        #region Methods

        void BwFillAttributesDoWork(object sender, DoWorkEventArgs e)
        {
            // Retrieve forms for this entity
            var allFormsDoc = MetadataHelper.RetrieveEntityForms(_emd.LogicalName, _service);

            foreach (var amd in _emd.Attributes)
            {
                if (amd.AttributeType == null ||
                    (amd.AttributeType.Value == AttributeTypeCode.Virtual || !string.IsNullOrEmpty(amd.AttributeOf)))
                    continue;

                var label = amd.DisplayName.UserLocalizedLabel != null ? amd.DisplayName.UserLocalizedLabel.Label : "N/A";

                var item = new ListViewItem(label);
                item.SubItems.Add(amd.LogicalName);
                item.SubItems.Add((allFormsDoc.SelectSingleNode("//control[@datafieldname='" + amd.LogicalName + "']") != null).ToString(CultureInfo.InvariantCulture));

                item.Tag = amd;
                  
                ListViewDelegates.AddItem(lvAttributes, item);
            }
        }

        void BwFillAttributesRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show(this, e.Error.Message, Resources.MessageBoxErrorHeader, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                if (_settings.EntitiesToProceed!= null && _settings.EntitiesToProceed.Any(x => x.Name == _emd.LogicalName))
                {
                    foreach (
                        var item in
                            lvAttributes.Items.Cast<ListViewItem>().Where(
                                item =>
                                _settings.EntitiesToProceed.First(x => x.Name == _emd.LogicalName).Attributes.Contains(item.SubItems[1].Text)))
                    {
                        item.Checked = true;
                    }
                }
            }
        }

        public GenerationSettings GetSettings()
        {
            if (!_settings.EntitiesToProceed.Any(x => x.Name == _emd.LogicalName))
            {
                _settings.EntitiesToProceed.Add(new EntityItem{Name = _emd.LogicalName, Attributes = new List<string>()});
            }

            _settings.EntitiesToProceed.First(x=>x.Name == _emd.LogicalName).Attributes.Clear();

            foreach (ListViewItem item in lvAttributes.CheckedItems)
            {
                _settings.EntitiesToProceed.First(x => x.Name == _emd.LogicalName).Attributes.Add(((AttributeMetadata)item.Tag).LogicalName);
            }

            return _settings;
        }

        #endregion Methods
    }
}
